@ -60,7 +60,7 @@ typedef enum NBDMode {
NBD_MODE_EXPORT_NAME , /* newstyle but only OPT_EXPORT_NAME safe */
NBD_MODE_SIMPLE , /* newstyle but only simple replies */
NBD_MODE_STRUCTURED , /* newstyle, structured replies enabled */
/* TODO add NBD_MODE_EXTENDED */
NBD_MODE_EXTENDED , /* newstyle, extended headers enabled */
} NBDMode ;
/* Transmission phase structs */
@ -93,20 +93,36 @@ typedef struct NBDStructuredReplyChunk {
uint32_t length ; /* length of payload */
} QEMU_PACKED NBDStructuredReplyChunk ;
typedef struct NBDExtendedReplyChunk {
uint32_t magic ; /* NBD_EXTENDED_REPLY_MAGIC */
uint16_t flags ; /* combination of NBD_REPLY_FLAG_* */
uint16_t type ; /* NBD_REPLY_TYPE_* */
uint64_t cookie ; /* request handle */
uint64_t offset ; /* request offset */
uint64_t length ; /* length of payload */
} QEMU_PACKED NBDExtendedReplyChunk ;
typedef union NBDReply {
NBDSimpleReply simple ;
NBDStructuredReplyChunk structured ;
NBDExtendedReplyChunk extended ;
struct {
/*
* @ magic and @ cookie 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
* @ magic and @ cookie fields have the same offset and size in all
* forms of replies , so let them be accessible without " .simple. " ,
* " .structured. " , or " .extend ed. " specifications .
*/
uint32_t magic ;
uint32_t _skip ;
uint64_t cookie ;
} QEMU_PACKED ;
} ;
} NBDReply ;
QEMU_BUILD_BUG_ON ( offsetof ( NBDReply , simple . cookie ) ! =
offsetof ( NBDReply , cookie ) ) ;
QEMU_BUILD_BUG_ON ( offsetof ( NBDReply , structured . cookie ) ! =
offsetof ( NBDReply , cookie ) ) ;
QEMU_BUILD_BUG_ON ( offsetof ( NBDReply , extended . cookie ) ! =
offsetof ( NBDReply , cookie ) ) ;
/* Header of chunk for NBD_REPLY_TYPE_OFFSET_DATA */
typedef struct NBDStructuredReadData {
@ -133,14 +149,34 @@ typedef struct NBDStructuredError {
typedef struct NBDStructuredMeta {
/* header's length >= 12 (at least one extent) */
uint32_t context_id ;
/* extents follows */
/* NBDExtent32 extents[] follows, array length implied by header */
} QEMU_PACKED NBDStructuredMeta ;
/* Extent chunk for NBD_REPLY_TYPE_BLOCK_STATUS */
typedef struct NBDExtent {
/* Extent array element for NBD_REPLY_TYPE_BLOCK_STATUS */
typedef struct NBDExtent32 {
uint32_t length ;
uint32_t flags ; /* NBD_STATE_* */
} QEMU_PACKED NBDExtent ;
} QEMU_PACKED NBDExtent32 ;
/* Header of NBD_REPLY_TYPE_BLOCK_STATUS_EXT */
typedef struct NBDExtendedMeta {
/* header's length >= 24 (at least one extent) */
uint32_t context_id ;
uint32_t count ; /* header length must be count * 16 + 8 */
/* NBDExtent64 extents[count] follows */
} QEMU_PACKED NBDExtendedMeta ;
/* Extent array element for NBD_REPLY_TYPE_BLOCK_STATUS_EXT */
typedef struct NBDExtent64 {
uint64_t length ;
uint64_t flags ; /* NBD_STATE_* */
} QEMU_PACKED NBDExtent64 ;
/* Client payload for limiting NBD_CMD_BLOCK_STATUS reply */
typedef struct NBDBlockStatusPayload {
uint64_t effect_length ;
/* uint32_t ids[] follows, array length implied by header */
} QEMU_PACKED NBDBlockStatusPayload ;
/* Transmission (export) flags: sent from server to client during handshake,
but describe what will happen during transmission */
@ -158,20 +194,22 @@ enum {
NBD_FLAG_SEND_RESIZE_BIT = 9 , /* Send resize */
NBD_FLAG_SEND_CACHE_BIT = 10 , /* Send CACHE (prefetch) */
NBD_FLAG_SEND_FAST_ZERO_BIT = 11 , /* FAST_ZERO flag for WRITE_ZEROES */
NBD_FLAG_BLOCK_STAT_PAYLOAD_BIT = 12 , /* PAYLOAD flag for BLOCK_STATUS */
} ;
# define NBD_FLAG_HAS_FLAGS (1 << NBD_FLAG_HAS_FLAGS_BIT)
# define NBD_FLAG_READ_ONLY (1 << NBD_FLAG_READ_ONLY_BIT)
# define NBD_FLAG_SEND_FLUSH (1 << NBD_FLAG_SEND_FLUSH_BIT)
# define NBD_FLAG_SEND_FUA (1 << NBD_FLAG_SEND_FUA_BIT)
# define NBD_FLAG_ROTATIONAL (1 << NBD_FLAG_ROTATIONAL_BIT)
# define NBD_FLAG_SEND_TRIM (1 << NBD_FLAG_SEND_TRIM_BIT)
# define NBD_FLAG_SEND_WRITE_ZEROES (1 << NBD_FLAG_SEND_WRITE_ZEROES_BIT)
# define NBD_FLAG_SEND_DF (1 << NBD_FLAG_SEND_DF_BIT)
# define NBD_FLAG_CAN_MULTI_CONN (1 << NBD_FLAG_CAN_MULTI_CONN_BIT)
# define NBD_FLAG_SEND_RESIZE (1 << NBD_FLAG_SEND_RESIZE_BIT)
# define NBD_FLAG_SEND_CACHE (1 << NBD_FLAG_SEND_CACHE_BIT)
# define NBD_FLAG_SEND_FAST_ZERO (1 << NBD_FLAG_SEND_FAST_ZERO_BIT)
# define NBD_FLAG_HAS_FLAGS (1 << NBD_FLAG_HAS_FLAGS_BIT)
# define NBD_FLAG_READ_ONLY (1 << NBD_FLAG_READ_ONLY_BIT)
# define NBD_FLAG_SEND_FLUSH (1 << NBD_FLAG_SEND_FLUSH_BIT)
# define NBD_FLAG_SEND_FUA (1 << NBD_FLAG_SEND_FUA_BIT)
# define NBD_FLAG_ROTATIONAL (1 << NBD_FLAG_ROTATIONAL_BIT)
# define NBD_FLAG_SEND_TRIM (1 << NBD_FLAG_SEND_TRIM_BIT)
# define NBD_FLAG_SEND_WRITE_ZEROES (1 << NBD_FLAG_SEND_WRITE_ZEROES_BIT)
# define NBD_FLAG_SEND_DF (1 << NBD_FLAG_SEND_DF_BIT)
# define NBD_FLAG_CAN_MULTI_CONN (1 << NBD_FLAG_CAN_MULTI_CONN_BIT)
# define NBD_FLAG_SEND_RESIZE (1 << NBD_FLAG_SEND_RESIZE_BIT)
# define NBD_FLAG_SEND_CACHE (1 << NBD_FLAG_SEND_CACHE_BIT)
# define NBD_FLAG_SEND_FAST_ZERO (1 << NBD_FLAG_SEND_FAST_ZERO_BIT)
# define NBD_FLAG_BLOCK_STAT_PAYLOAD (1 << NBD_FLAG_BLOCK_STAT_PAYLOAD_BIT)
/* New-style handshake (global) flags, sent from server to client, and
control what will happen during handshake phase . */
@ -194,6 +232,7 @@ enum {
# define NBD_OPT_STRUCTURED_REPLY (8)
# define NBD_OPT_LIST_META_CONTEXT (9)
# define NBD_OPT_SET_META_CONTEXT (10)
# define NBD_OPT_EXTENDED_HEADERS (11)
/* Option reply types. */
# define NBD_REP_ERR(value) ((UINT32_C(1) << 31) | (value))
@ -211,6 +250,8 @@ enum {
# define NBD_REP_ERR_UNKNOWN NBD_REP_ERR(6) /* Export unknown */
# define NBD_REP_ERR_SHUTDOWN NBD_REP_ERR(7) /* Server shutting down */
# define NBD_REP_ERR_BLOCK_SIZE_REQD NBD_REP_ERR(8) /* Need INFO_BLOCK_SIZE */
# define NBD_REP_ERR_TOO_BIG NBD_REP_ERR(9) /* Payload size overflow */
# define NBD_REP_ERR_EXT_HEADER_REQD NBD_REP_ERR(10) /* Need extended headers */
/* Info types, used during NBD_REP_INFO */
# define NBD_INFO_EXPORT 0
@ -219,12 +260,14 @@ enum {
# define NBD_INFO_BLOCK_SIZE 3
/* 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 */
# define NBD_CMD_FLAG_REQ_ONE (1 << 3) / * only one extent in BLOCK_STATUS
* reply chunk */
# define NBD_CMD_FLAG_FAST_ZERO (1 << 4) /* fail if WRITE_ZEROES is not fast */
# 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 */
# define NBD_CMD_FLAG_REQ_ONE (1 << 3) \
/* only one extent in BLOCK_STATUS reply chunk */
# define NBD_CMD_FLAG_FAST_ZERO (1 << 4) /* fail if WRITE_ZEROES is not fast */
# define NBD_CMD_FLAG_PAYLOAD_LEN (1 << 5) \
/* length describes payload, not effect; only with ext header */
/* Supported request types */
enum {
@ -250,22 +293,31 @@ enum {
*/
# define NBD_MAX_STRING_SIZE 4096
/* Two types of reply structures */
/* Two types of request structures, a given client will only use 1 */
# define NBD_REQUEST_MAGIC 0x25609513
# define NBD_EXTENDED_REQUEST_MAGIC 0x21e41c71
/*
* Three types of reply structures , but what a client expects depends
* on NBD_OPT_STRUCTURED_REPLY and NBD_OPT_EXTENDED_HEADERS .
*/
# define NBD_SIMPLE_REPLY_MAGIC 0x67446698
# define NBD_STRUCTURED_REPLY_MAGIC 0x668e33ef
# define NBD_EXTENDED_REPLY_MAGIC 0x6e8a278c
/* Structured reply flags */
/* Chunk reply flags (for structured and extended replies) */
# define NBD_REPLY_FLAG_DONE (1 << 0) /* This reply-chunk is last */
/* Structured reply types */
/* Chunk 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_BLOCK_STATUS 5
# define NBD_REPLY_TYPE_ERROR NBD_REPLY_ERR(1)
# define NBD_REPLY_TYPE_ERROR_OFFSET NBD_REPLY_ERR(2)
# define NBD_REPLY_TYPE_NONE 0
# define NBD_REPLY_TYPE_OFFSET_DATA 1
# define NBD_REPLY_TYPE_OFFSET_HOLE 2
# define NBD_REPLY_TYPE_BLOCK_STATUS 5
# define NBD_REPLY_TYPE_BLOCK_STATUS_EXT 6
# define NBD_REPLY_TYPE_ERROR NBD_REPLY_ERR(1)
# define NBD_REPLY_TYPE_ERROR_OFFSET NBD_REPLY_ERR(2)
/* Extent flags for base:allocation in NBD_REPLY_TYPE_BLOCK_STATUS */
# define NBD_STATE_HOLE (1 << 0)