[Libguestfs] [PATCH nbdkit 3/8] server: Implement Block Status requests to read allocation status.
Eric Blake
eblake at redhat.com
Sat Mar 23 16:51:15 UTC 2019
On 3/20/19 5:11 PM, Richard W.M. Jones wrote:
> This commit implements the core NBD protocol for the "base:allocation"
> Block Status replies.
> ---
> server/internal.h | 7 ++
> server/protocol.h | 15 +++
> server/protocol-handshake-newstyle.c | 81 ++++++++++++++-
> server/protocol.c | 141 ++++++++++++++++++++++++---
> 4 files changed, 229 insertions(+), 15 deletions(-)
>
> +static int
> +send_structured_reply_block_status (struct connection *conn,
> + uint64_t handle,
> + uint16_t cmd, uint16_t flags,
> + uint32_t count, uint64_t offset,
> + struct nbdkit_extents *extents)
> +{
> + ACQUIRE_LOCK_FOR_CURRENT_SCOPE (&conn->write_lock);
> + struct structured_reply reply;
> + size_t nr_extents = nbdkit_extents_size (extents);
> + uint32_t context_id;
> + size_t i;
> + int r;
> +
> + assert (cmd == NBD_CMD_BLOCK_STATUS);
> +
Worth asserting conn->meta_context_base_allocation?
> +
> + /* Send each block descriptor. */
> + for (i = 0; i < nr_extents; ++i) {
Where does the list terminate after 1 extent if REQ_ONE was set? Also,
if REQ_ONE is set but the plugin provided coalesced status beyond the
request, this would need to clamp the answer to the requested length.
> + const struct nbdkit_extent e = nbdkit_get_extent (extents, i);
> + struct block_descriptor bd;
> +
> + if (i == 0)
> + assert (e.offset == offset);
> +
> + bd.length = htobe32 (e.length);
> + bd.status_flags = htobe32 (e.type & 3);
> +
> + r = conn->send (conn, &bd, sizeof bd);
> + if (r == -1) {
> + nbdkit_error ("write reply: %s: %m", name_of_nbd_cmd (cmd));
> + return connection_set_status (conn, -1);
> + }
> + }
Where does the list terminate once you send the final extent that
overlaps the end of the original request? (If you implement my idea of
tracking a maximum offset in nbdkit_extents in patch 1, this may be
picked up automatically)
> @@ -498,15 +605,23 @@ protocol_recv_request_send_reply (struct connection *conn)
> }
>
> /* Currently we prefer to send simple replies for everything except
> - * where we have to (ie. NBD_CMD_READ when structured_replies have
> - * been negotiated). However this prevents us from sending
> - * human-readable error messages to the client, so we should
> - * reconsider this in future.
> + * where we have to (ie. NBD_CMD_READ and NBD_CMD_BLOCK_STATUS when
> + * structured_replies have been negotiated). However this prevents
> + * us from sending human-readable error messages to the client, so
> + * we should reconsider this in future.
> */
> - if (conn->structured_replies && cmd == NBD_CMD_READ) {
> - if (!error)
> - return send_structured_reply_read (conn, request.handle, cmd,
> - buf, count, offset);
> + if (conn->structured_replies &&
> + (cmd == NBD_CMD_READ || cmd == NBD_CMD_BLOCK_STATUS)) {
> + if (!error) {
> + if (cmd == NBD_CMD_READ)
> + return send_structured_reply_read (conn, request.handle, cmd,
> + buf, count, offset);
> + else /* NBD_CMD_BLOCK_STATUS */
> + return send_structured_reply_block_status (conn, request.handle,
> + cmd, flags,
> + count, offset,
> + extents);
> + }
> else
> return send_structured_reply_error (conn, request.handle, cmd, error);
Ah, so you are already sending a structured error, even though the
protocol didn't require it (which is the qemu bug I just sent a patch
for today). Technically, the protocol requires a structured error for
NBD_CMD_READ, but permits a simple error for NBD_CMD_BLOCK_STATUS; but
portability wise, since qemu 2.12 through 3.1 choke on the simple error,
this works around those versions of qemu.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3226
Virtualization: qemu.org | libvirt.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libguestfs/attachments/20190323/177ffc04/attachment.sig>
More information about the Libguestfs
mailing list