Commit 2e7b7665 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2018-03-01' into staging



nbd patches for 2018-03-01

- Eric Blake: nbd: Honor server's advertised minimum block size
- Vladimir Sementsov-Ogievskiy: partial: nbd block status base:allocation

# gpg: Signature made Thu 01 Mar 2018 21:01:22 GMT
# gpg:                using RSA key A7A16B4A2527436A
# 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-2018-03-01:
  nbd/client: fix error messages in nbd_handle_reply_err
  nbd: BLOCK_STATUS constants
  nbd: change indenting in nbd.h
  nbd: Honor server's advertised minimum block size

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 427cbc7e 28fb494f
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -846,9 +846,6 @@ int nbd_client_init(BlockDriverState *bs,
    if (client->info.flags & NBD_FLAG_SEND_WRITE_ZEROES) {
        bs->supported_zero_flags |= BDRV_REQ_MAY_UNMAP;
    }
    if (client->info.min_block > bs->bl.request_alignment) {
        bs->bl.request_alignment = client->info.min_block;
    }

    qemu_co_mutex_init(&client->send_mutex);
    qemu_co_queue_init(&client->free_sema);
+2 −0
Original line number Diff line number Diff line
@@ -474,8 +474,10 @@ static int nbd_co_flush(BlockDriverState *bs)
static void nbd_refresh_limits(BlockDriverState *bs, Error **errp)
{
    NBDClientSession *s = nbd_get_client_session(bs);
    uint32_t min = s->info.min_block;
    uint32_t max = MIN_NON_ZERO(NBD_MAX_BUFFER_SIZE, s->info.max_block);

    bs->bl.request_alignment = min ? min : BDRV_SECTOR_SIZE;
    bs->bl.max_pdiscard = max;
    bs->bl.max_pwrite_zeroes = max;
    bs->bl.max_transfer = max;
+42 −11
Original line number Diff line number Diff line
@@ -41,6 +41,12 @@ struct NBDOptionReply {
} QEMU_PACKED;
typedef struct NBDOptionReply NBDOptionReply;

typedef struct NBDOptionReplyMetaContext {
    NBDOptionReply h; /* h.type = NBD_REP_META_CONTEXT, h.length > 4 */
    uint32_t context_id;
    /* meta context name follows */
} QEMU_PACKED NBDOptionReplyMetaContext;

/* Transmission phase structs
 *
 * Note: these are _NOT_ the same as the network representation of an NBD
@@ -105,6 +111,19 @@ typedef struct NBDStructuredError {
    uint16_t message_length;
} QEMU_PACKED NBDStructuredError;

/* Header of NBD_REPLY_TYPE_BLOCK_STATUS */
typedef struct NBDStructuredMeta {
    NBDStructuredReplyChunk h; /* h.length >= 12 (at least one extent) */
    uint32_t context_id;
    /* extents follows */
} QEMU_PACKED NBDStructuredMeta;

/* Extent chunk for NBD_REPLY_TYPE_BLOCK_STATUS */
typedef struct NBDExtent {
    uint32_t length;
    uint32_t flags; /* NBD_STATE_* */
} QEMU_PACKED NBDExtent;

/* 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 */
@@ -136,6 +155,8 @@ typedef struct NBDStructuredError {
#define NBD_OPT_INFO              (6)
#define NBD_OPT_GO                (7)
#define NBD_OPT_STRUCTURED_REPLY  (8)
#define NBD_OPT_LIST_META_CONTEXT (9)
#define NBD_OPT_SET_META_CONTEXT  (10)

/* Option reply types. */
#define NBD_REP_ERR(value) ((UINT32_C(1) << 31) | (value))
@@ -143,6 +164,7 @@ typedef struct NBDStructuredError {
#define NBD_REP_ACK             (1)    /* Data sending finished. */
#define NBD_REP_SERVER          (2)    /* Export description. */
#define NBD_REP_INFO            (3)    /* NBD_OPT_INFO/GO. */
#define NBD_REP_META_CONTEXT    (4)    /* NBD_OPT_{LIST,SET}_META_CONTEXT */

#define NBD_REP_ERR_UNSUP           NBD_REP_ERR(1)  /* Unknown option */
#define NBD_REP_ERR_POLICY          NBD_REP_ERR(2)  /* Server denied */
@@ -163,6 +185,8 @@ typedef struct NBDStructuredError {
#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 */

/* Supported request types */
enum {
@@ -173,6 +197,7 @@ enum {
    NBD_CMD_TRIM = 4,
    /* 5 reserved for failed experiment NBD_CMD_CACHE */
    NBD_CMD_WRITE_ZEROES = 6,
    NBD_CMD_BLOCK_STATUS = 7,
};

#define NBD_DEFAULT_PORT	10809
@@ -200,9 +225,15 @@ enum {
#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)

/* Flags for extents (NBDExtent.flags) of NBD_REPLY_TYPE_BLOCK_STATUS,
 * for base:allocation meta context */
#define NBD_STATE_HOLE (1 << 0)
#define NBD_STATE_ZERO (1 << 1)

static inline bool nbd_reply_type_is_error(int type)
{
    return type & (1 << 15);
+12 −12
Original line number Diff line number Diff line
@@ -158,14 +158,14 @@ static int nbd_handle_reply_err(QIOChannel *ioc, NBDOptionReply *reply,

    if (reply->length) {
        if (reply->length > NBD_MAX_BUFFER_SIZE) {
            error_setg(errp, "server error 0x%" PRIx32
            error_setg(errp, "server error %" PRIu32
                       " (%s) message is too long",
                       reply->type, nbd_rep_lookup(reply->type));
            goto cleanup;
        }
        msg = g_malloc(reply->length + 1);
        if (nbd_read(ioc, msg, reply->length, errp) < 0) {
            error_prepend(errp, "failed to read option error 0x%" PRIx32
            error_prepend(errp, "failed to read option error %" PRIu32
                          " (%s) message: ",
                          reply->type, nbd_rep_lookup(reply->type));
            goto cleanup;
@@ -180,22 +180,22 @@ static int nbd_handle_reply_err(QIOChannel *ioc, NBDOptionReply *reply,
        goto cleanup;

    case NBD_REP_ERR_POLICY:
        error_setg(errp, "Denied by server for option %" PRIx32 " (%s)",
        error_setg(errp, "Denied by server for option %" PRIu32 " (%s)",
                   reply->option, nbd_opt_lookup(reply->option));
        break;

    case NBD_REP_ERR_INVALID:
        error_setg(errp, "Invalid data length for option %" PRIx32 " (%s)",
        error_setg(errp, "Invalid parameters for option %" PRIu32 " (%s)",
                   reply->option, nbd_opt_lookup(reply->option));
        break;

    case NBD_REP_ERR_PLATFORM:
        error_setg(errp, "Server lacks support for option %" PRIx32 " (%s)",
        error_setg(errp, "Server lacks support for option %" PRIu32 " (%s)",
                   reply->option, nbd_opt_lookup(reply->option));
        break;

    case NBD_REP_ERR_TLS_REQD:
        error_setg(errp, "TLS negotiation required before option %" PRIx32
        error_setg(errp, "TLS negotiation required before option %" PRIu32
                   " (%s)", reply->option, nbd_opt_lookup(reply->option));
        break;

@@ -204,17 +204,17 @@ static int nbd_handle_reply_err(QIOChannel *ioc, NBDOptionReply *reply,
        break;

    case NBD_REP_ERR_SHUTDOWN:
        error_setg(errp, "Server shutting down before option %" PRIx32 " (%s)",
        error_setg(errp, "Server shutting down before option %" PRIu32 " (%s)",
                   reply->option, nbd_opt_lookup(reply->option));
        break;

    case NBD_REP_ERR_BLOCK_SIZE_REQD:
        error_setg(errp, "Server requires INFO_BLOCK_SIZE for option %" PRIx32
        error_setg(errp, "Server requires INFO_BLOCK_SIZE for option %" PRIu32
                   " (%s)", reply->option, nbd_opt_lookup(reply->option));
        break;

    default:
        error_setg(errp, "Unknown error code when asking for option %" PRIx32
        error_setg(errp, "Unknown error code when asking for option %" PRIu32
                   " (%s)", reply->option, nbd_opt_lookup(reply->option));
        break;
    }
@@ -378,8 +378,8 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname,
            return 1;
        }
        if (reply.type != NBD_REP_INFO) {
            error_setg(errp, "unexpected reply type %" PRIx32
                       " (%s), expected %x",
            error_setg(errp, "unexpected reply type %" PRIu32
                       " (%s), expected %u",
                       reply.type, nbd_rep_lookup(reply.type), NBD_REP_INFO);
            nbd_send_opt_abort(ioc);
            return -1;
@@ -534,7 +534,7 @@ static int nbd_request_simple_option(QIOChannel *ioc, int opt, Error **errp)

    if (reply.type != NBD_REP_ACK) {
        error_setg(errp, "Server answered option %d (%s) with unexpected "
                   "reply %" PRIx32 " (%s)", opt, nbd_opt_lookup(opt),
                   "reply %" PRIu32 " (%s)", opt, nbd_opt_lookup(opt),
                   reply.type, nbd_rep_lookup(reply.type));
        nbd_send_opt_abort(ioc);
        return -1;
+10 −0
Original line number Diff line number Diff line
@@ -75,6 +75,10 @@ const char *nbd_opt_lookup(uint32_t opt)
        return "go";
    case NBD_OPT_STRUCTURED_REPLY:
        return "structured reply";
    case NBD_OPT_LIST_META_CONTEXT:
        return "list meta context";
    case NBD_OPT_SET_META_CONTEXT:
        return "set meta context";
    default:
        return "<unknown>";
    }
@@ -90,6 +94,8 @@ const char *nbd_rep_lookup(uint32_t rep)
        return "server";
    case NBD_REP_INFO:
        return "info";
    case NBD_REP_META_CONTEXT:
        return "meta context";
    case NBD_REP_ERR_UNSUP:
        return "unsupported";
    case NBD_REP_ERR_POLICY:
@@ -144,6 +150,8 @@ const char *nbd_cmd_lookup(uint16_t cmd)
        return "trim";
    case NBD_CMD_WRITE_ZEROES:
        return "write zeroes";
    case NBD_CMD_BLOCK_STATUS:
        return "block status";
    default:
        return "<unknown>";
    }
@@ -159,6 +167,8 @@ const char *nbd_reply_type_lookup(uint16_t type)
        return "data";
    case NBD_REPLY_TYPE_OFFSET_HOLE:
        return "hole";
    case NBD_REPLY_TYPE_BLOCK_STATUS:
        return "block status";
    case NBD_REPLY_TYPE_ERROR:
        return "generic error";
    case NBD_REPLY_TYPE_ERROR_OFFSET:
Loading