diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2017-10-31 13:12:21 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2017-10-31 13:12:21 +0000 |
commit | 92c7ec5cd4d15c76218703f7bd3ca75bd46353b7 (patch) | |
tree | 0e17111be31efbc5ab657c4736b3e8556b4cf191 /include | |
parent | d2b9d71432687eef947f243a57409381151701d5 (diff) | |
parent | f140e3000371e67ff4e00df3213e2d576d9c91be (diff) | |
download | qemu-92c7ec5cd4d15c76218703f7bd3ca75bd46353b7.zip qemu-92c7ec5cd4d15c76218703f7bd3ca75bd46353b7.tar.gz qemu-92c7ec5cd4d15c76218703f7bd3ca75bd46353b7.tar.bz2 |
Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2017-10-30' into staging
nbd patches for 2017-10-30
Vladimir Sementsov-Ogievskiy (some patches co-authored by Eric Blake):
00/12 nbd minimal structured read
# gpg: Signature made Mon 30 Oct 2017 20:54:54 GMT
# gpg: using RSA key 0xA7A16B4A2527436A
# gpg: Good signature from "Eric Blake <eblake@redhat.com>"
# gpg: aka "Eric Blake (Free Software Programmer) <ebb9@byu.net>"
# gpg: aka "[jpeg image of size 6874]"
# Primary key fingerprint: 71C2 CC22 B1C4 6029 27D2 F3AA A7A1 6B4A 2527 436A
* remotes/ericb/tags/pull-nbd-2017-10-30:
nbd: Minimal structured read for client
nbd: Move nbd_read() to common header
nbd/client: prepare nbd_receive_reply for structured reply
nbd/client: refactor nbd_receive_starttls
nbd/server: Include human-readable message in structured errors
nbd: Minimal structured read for server
nbd/server: Refactor zero-length option check
nbd/server: Simplify nbd_negotiate_options loop
nbd/server: Report error for write to read-only export
nbd: Expose constants and structs for structured read
nbd: Move nbd_errno_to_system_errno() to public header
nbd: Include error names in trace messages
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/block/nbd.h | 106 |
1 files changed, 100 insertions, 6 deletions
diff --git a/include/block/nbd.h b/include/block/nbd.h index a6df5ce..92d1723 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -57,18 +57,48 @@ struct NBDRequest { }; typedef struct NBDRequest NBDRequest; -struct NBDReply { - uint64_t handle; - uint32_t error; -}; -typedef struct NBDReply NBDReply; - typedef struct NBDSimpleReply { uint32_t magic; /* NBD_SIMPLE_REPLY_MAGIC */ uint32_t error; uint64_t handle; } QEMU_PACKED NBDSimpleReply; +/* Header of all structured replies */ +typedef struct NBDStructuredReplyChunk { + uint32_t magic; /* NBD_STRUCTURED_REPLY_MAGIC */ + uint16_t flags; /* combination of NBD_REPLY_FLAG_* */ + uint16_t type; /* NBD_REPLY_TYPE_* */ + uint64_t handle; /* request handle */ + uint32_t length; /* length of payload */ +} QEMU_PACKED NBDStructuredReplyChunk; + +typedef union NBDReply { + NBDSimpleReply simple; + NBDStructuredReplyChunk structured; + struct { + /* @magic and @handle fields have the same offset and size both in + * simple reply and structured reply chunk, so let them be accessible + * without ".simple." or ".structured." specification + */ + uint32_t magic; + uint32_t _skip; + uint64_t handle; + } QEMU_PACKED; +} NBDReply; + +/* Header of NBD_REPLY_TYPE_OFFSET_DATA, complete NBD_REPLY_TYPE_OFFSET_HOLE */ +typedef struct NBDStructuredRead { + NBDStructuredReplyChunk h; + uint64_t offset; +} QEMU_PACKED NBDStructuredRead; + +/* Header of all NBD_REPLY_TYPE_ERROR* errors */ +typedef struct NBDStructuredError { + NBDStructuredReplyChunk h; + uint32_t error; + uint16_t message_length; +} QEMU_PACKED NBDStructuredError; + /* Transmission (export) flags: sent from server to client during handshake, but describe what will happen during transmission */ #define NBD_FLAG_HAS_FLAGS (1 << 0) /* Flags are there */ @@ -79,6 +109,7 @@ typedef struct NBDSimpleReply { rotational media */ #define NBD_FLAG_SEND_TRIM (1 << 5) /* Send TRIM (discard) */ #define NBD_FLAG_SEND_WRITE_ZEROES (1 << 6) /* Send WRITE_ZEROES */ +#define NBD_FLAG_SEND_DF (1 << 7) /* Send DF (Do not Fragment) */ /* New-style handshake (global) flags, sent from server to client, and control what will happen during handshake phase. */ @@ -125,6 +156,7 @@ typedef struct NBDSimpleReply { /* Request flags, sent from client to server during transmission phase */ #define NBD_CMD_FLAG_FUA (1 << 0) /* 'force unit access' during write */ #define NBD_CMD_FLAG_NO_HOLE (1 << 1) /* don't punch hole on zero run */ +#define NBD_CMD_FLAG_DF (1 << 2) /* don't fragment structured read */ /* Supported request types */ enum { @@ -149,10 +181,49 @@ enum { * aren't overflowing some other buffer. */ #define NBD_MAX_NAME_SIZE 256 +/* Two types of reply structures */ +#define NBD_SIMPLE_REPLY_MAGIC 0x67446698 +#define NBD_STRUCTURED_REPLY_MAGIC 0x668e33ef + +/* Structured reply flags */ +#define NBD_REPLY_FLAG_DONE (1 << 0) /* This reply-chunk is last */ + +/* Structured reply types */ +#define NBD_REPLY_ERR(value) ((1 << 15) | (value)) + +#define NBD_REPLY_TYPE_NONE 0 +#define NBD_REPLY_TYPE_OFFSET_DATA 1 +#define NBD_REPLY_TYPE_OFFSET_HOLE 2 +#define NBD_REPLY_TYPE_ERROR NBD_REPLY_ERR(1) +#define NBD_REPLY_TYPE_ERROR_OFFSET NBD_REPLY_ERR(2) + +static inline bool nbd_reply_type_is_error(int type) +{ + return type & (1 << 15); +} + +/* NBD errors are based on errno numbers, so there is a 1:1 mapping, + * but only a limited set of errno values is specified in the protocol. + * Everything else is squashed to EINVAL. + */ +#define NBD_SUCCESS 0 +#define NBD_EPERM 1 +#define NBD_EIO 5 +#define NBD_ENOMEM 12 +#define NBD_EINVAL 22 +#define NBD_ENOSPC 28 +#define NBD_EOVERFLOW 75 +#define NBD_ESHUTDOWN 108 + /* Details collected by NBD_OPT_EXPORT_NAME and NBD_OPT_GO */ struct NBDExportInfo { /* Set by client before nbd_receive_negotiate() */ bool request_sizes; + + /* In-out fields, set by client before nbd_receive_negotiate() and + * updated by server results during nbd_receive_negotiate() */ + bool structured_reply; + /* Set by server results during nbd_receive_negotiate() */ uint64_t size; uint16_t flags; @@ -172,6 +243,7 @@ int nbd_send_request(QIOChannel *ioc, NBDRequest *request); int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp); int nbd_client(int fd); int nbd_disconnect(int fd); +int nbd_errno_to_system_errno(int err); typedef struct NBDExport NBDExport; typedef struct NBDClient NBDClient; @@ -202,4 +274,26 @@ void nbd_client_put(NBDClient *client); void nbd_server_start(SocketAddress *addr, const char *tls_creds, Error **errp); + +/* nbd_read + * Reads @size bytes from @ioc. Returns 0 on success. + */ +static inline int nbd_read(QIOChannel *ioc, void *buffer, size_t size, + Error **errp) +{ + return qio_channel_read_all(ioc, buffer, size, errp) < 0 ? -EIO : 0; +} + +static inline bool nbd_reply_is_simple(NBDReply *reply) +{ + return reply->magic == NBD_SIMPLE_REPLY_MAGIC; +} + +static inline bool nbd_reply_is_structured(NBDReply *reply) +{ + return reply->magic == NBD_STRUCTURED_REPLY_MAGIC; +} + +const char *nbd_reply_type_lookup(uint16_t type); + #endif |