Commit a2964459 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2019-01-05' into staging



nbd patches for 2019-01-05

Error and trace improvements in NBD code, such as less noise for
common disconnect scenarios.

- Vladimir Sementsov-Ogievskiy: 0/3 nbd-client: drop extra error noise
- Eric Blake: portions of 0/22 nbd: add qemu-nbd --list

# gpg: Signature made Sat 05 Jan 2019 13:58:54 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-2019-01-05:
  nbd/client: Drop pointless buf variable
  qemu-nbd: Fail earlier for -c/-d on non-linux
  nbd/client: More consistent error messages
  nbd: Document timeline of various features
  qemu-nbd: Use program name in error messages
  block/nbd-client: use traces instead of noisy error_report_err
  nbd/client: Trace all server option error messages
  nbd: publish _lookup functions

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents e59dbbac ef2e35fc
Loading
Loading
Loading
Loading
+19 −4
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@
 */

#include "qemu/osdep.h"

#include "trace.h"
#include "qapi/error.h"
#include "nbd-client.h"

@@ -79,7 +81,8 @@ static coroutine_fn void nbd_read_reply_entry(void *opaque)
        assert(s->reply.handle == 0);
        ret = nbd_receive_reply(s->ioc, &s->reply, &local_err);
        if (local_err) {
            error_report_err(local_err);
            trace_nbd_read_reply_entry_fail(ret, error_get_pretty(local_err));
            error_free(local_err);
        }
        if (ret <= 0) {
            break;
@@ -771,7 +774,11 @@ static int nbd_co_request(BlockDriverState *bs, NBDRequest *request,

    ret = nbd_co_receive_return_code(client, request->handle, &local_err);
    if (local_err) {
        error_report_err(local_err);
        trace_nbd_co_request_fail(request->from, request->len, request->handle,
                                  request->flags, request->type,
                                  nbd_cmd_lookup(request->type),
                                  ret, error_get_pretty(local_err));
        error_free(local_err);
    }
    return ret;
}
@@ -802,7 +809,11 @@ int nbd_client_co_preadv(BlockDriverState *bs, uint64_t offset,
    ret = nbd_co_receive_cmdread_reply(client, request.handle, offset, qiov,
                                       &local_err);
    if (local_err) {
        error_report_err(local_err);
        trace_nbd_co_request_fail(request.from, request.len, request.handle,
                                  request.flags, request.type,
                                  nbd_cmd_lookup(request.type),
                                  ret, error_get_pretty(local_err));
        error_free(local_err);
    }
    return ret;
}
@@ -925,7 +936,11 @@ int coroutine_fn nbd_client_co_block_status(BlockDriverState *bs,
    ret = nbd_co_receive_blockstatus_reply(client, request.handle, bytes,
                                           &extent, &local_err);
    if (local_err) {
        error_report_err(local_err);
        trace_nbd_co_request_fail(request.from, request.len, request.handle,
                                  request.flags, request.type,
                                  nbd_cmd_lookup(request.type),
                                  ret, error_get_pretty(local_err));
        error_free(local_err);
    }
    if (ret < 0) {
        return ret;
+4 −0
Original line number Diff line number Diff line
@@ -156,3 +156,7 @@ nvme_cmd_map_qiov_iov(void *s, int i, void *page, int pages) "s %p iov[%d] %p pa

# block/iscsi.c
iscsi_xcopy(void *src_lun, uint64_t src_off, void *dst_lun, uint64_t dst_off, uint64_t bytes, int ret) "src_lun %p offset %"PRIu64" dst_lun %p offset %"PRIu64" bytes %"PRIu64" ret %d"

# block/nbd-client.c
nbd_read_reply_entry_fail(int ret, const char *err) "ret = %d, err: %s"
nbd_co_request_fail(uint64_t from, uint32_t len, uint64_t handle, uint16_t flags, uint16_t type, const char *name, int ret, const char *err) "Request failed { .from = %" PRIu64", .len = %" PRIu32 ", .handle = %" PRIu64 ", .flags = 0x%" PRIx16 ", .type = %" PRIu16 " (%s) } ret = %d, err: %s"
+18 −1
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@ Qemu supports the "base:allocation" metadata context as defined in the
NBD protocol specification, and also defines an additional metadata
namespace "qemu".


== "qemu" namespace ==

The "qemu" namespace currently contains only one type of context,
@@ -36,3 +35,21 @@ in addition to "qemu:dirty-bitmap:<dirty-bitmap-export-name>":
            namespace.
* "qemu:dirty-bitmap:" - returns list of all available dirty-bitmap
                         metadata contexts.

= Features by version =

The following list documents which qemu version first implemented
various features (both as a server exposing the feature, and as a
client taking advantage of the feature when present), to make it
easier to plan for cross-version interoperability.  Note that in
several cases, the initial release containing a feature may require
additional patches from the corresponding stable branch to fix bugs in
the operation of that feature.

* 2.6: NBD_OPT_STARTTLS with TLS X.509 Certificates
* 2.8: NBD_CMD_WRITE_ZEROES
* 2.10: NBD_OPT_GO, NBD_INFO_BLOCK
* 2.11: NBD_OPT_STRUCTURED_REPLY
* 2.12: NBD_CMD_BLOCK_STATUS for "base:allocation"
* 3.0: NBD_OPT_STARTTLS with TLS Pre-Shared Keys (PSK),
NBD_CMD_BLOCK_STATUS for "qemu:dirty-bitmap:", NBD_CMD_CACHE
+5 −0
Original line number Diff line number Diff line
@@ -343,5 +343,10 @@ static inline bool nbd_reply_is_structured(NBDReply *reply)
}

const char *nbd_reply_type_lookup(uint16_t type);
const char *nbd_opt_lookup(uint32_t opt);
const char *nbd_rep_lookup(uint32_t rep);
const char *nbd_info_lookup(uint16_t info);
const char *nbd_cmd_lookup(uint16_t info);
const char *nbd_err_lookup(int err);

#endif
+22 −41
Original line number Diff line number Diff line
@@ -132,8 +132,9 @@ static int nbd_receive_option_reply(QIOChannel *ioc, uint32_t opt,
        return -1;
    }
    if (reply->option != opt) {
        error_setg(errp, "Unexpected option type %x expected %x",
                   reply->option, opt);
        error_setg(errp, "Unexpected option type %u (%s), expected %u (%s)",
                   reply->option, nbd_opt_lookup(reply->option),
                   opt, nbd_opt_lookup(opt));
        nbd_send_opt_abort(ioc);
        return -1;
    }
@@ -171,6 +172,8 @@ static int nbd_handle_reply_err(QIOChannel *ioc, NBDOptionReply *reply,
            goto cleanup;
        }
        msg[reply->length] = '\0';
        trace_nbd_server_error_msg(reply->type,
                                   nbd_reply_type_lookup(reply->type), msg);
    }

    switch (reply->type) {
@@ -265,8 +268,9 @@ static int nbd_receive_list(QIOChannel *ioc, const char *want, bool *match,
        }
        return 0;
    } else if (reply.type != NBD_REP_SERVER) {
        error_setg(errp, "Unexpected reply type %" PRIx32 " expected %x",
                   reply.type, NBD_REP_SERVER);
        error_setg(errp, "Unexpected reply type %u (%s), expected %u (%s)",
                   reply.type, nbd_rep_lookup(reply.type),
                   NBD_REP_SERVER, nbd_rep_lookup(NBD_REP_SERVER));
        nbd_send_opt_abort(ioc);
        return -1;
    }
@@ -378,9 +382,9 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname,
            return 1;
        }
        if (reply.type != NBD_REP_INFO) {
            error_setg(errp, "unexpected reply type %" PRIu32
                       " (%s), expected %u",
                       reply.type, nbd_rep_lookup(reply.type), NBD_REP_INFO);
            error_setg(errp, "unexpected reply type %u (%s), expected %u (%s)",
                       reply.type, nbd_rep_lookup(reply.type),
                       NBD_REP_INFO, nbd_rep_lookup(NBD_REP_INFO));
            nbd_send_opt_abort(ioc);
            return -1;
        }
@@ -704,8 +708,9 @@ static int nbd_negotiate_simple_meta_context(QIOChannel *ioc,
    }

    if (reply.type != NBD_REP_ACK) {
        error_setg(errp, "Unexpected reply type %" PRIx32 " expected %x",
                   reply.type, NBD_REP_ACK);
        error_setg(errp, "Unexpected reply type %u (%s), expected %u (%s)",
                   reply.type, nbd_rep_lookup(reply.type),
                   NBD_REP_ACK, nbd_rep_lookup(NBD_REP_ACK));
        nbd_send_opt_abort(ioc);
        return -1;
    }
@@ -728,7 +733,6 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
                          QIOChannel **outioc, NBDExportInfo *info,
                          Error **errp)
{
    char buf[256];
    uint64_t magic;
    int rc;
    bool zeroes = true;
@@ -749,27 +753,20 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
        goto fail;
    }

    if (nbd_read(ioc, buf, 8, errp) < 0) {
        error_prepend(errp, "Failed to read data: ");
        goto fail;
    }

    buf[8] = '\0';
    if (strlen(buf) == 0) {
        error_setg(errp, "Server connection closed unexpectedly");
    if (nbd_read(ioc, &magic, sizeof(magic), errp) < 0) {
        error_prepend(errp, "Failed to read initial magic: ");
        goto fail;
    }

    magic = ldq_be_p(buf);
    magic = be64_to_cpu(magic);
    trace_nbd_receive_negotiate_magic(magic);

    if (memcmp(buf, "NBDMAGIC", 8) != 0) {
        error_setg(errp, "Invalid magic received");
    if (magic != NBD_INIT_MAGIC) {
        error_setg(errp, "Bad initial magic received: 0x%" PRIx64, magic);
        goto fail;
    }

    if (nbd_read(ioc, &magic, sizeof(magic), errp) < 0) {
        error_prepend(errp, "Failed to read magic: ");
        error_prepend(errp, "Failed to read server magic: ");
        goto fail;
    }
    magic = be64_to_cpu(magic);
@@ -908,7 +905,7 @@ int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
        }
        info->flags = oldflags;
    } else {
        error_setg(errp, "Bad magic received");
        error_setg(errp, "Bad server magic received: 0x%" PRIx64, magic);
        goto fail;
    }

@@ -1026,23 +1023,7 @@ int nbd_disconnect(int fd)
    return 0;
}

#else
int nbd_init(int fd, QIOChannelSocket *ioc, NBDExportInfo *info,
	     Error **errp)
{
    error_setg(errp, "nbd_init is only supported on Linux");
    return -ENOTSUP;
}

int nbd_client(int fd)
{
    return -ENOTSUP;
}
int nbd_disconnect(int fd)
{
    return -ENOTSUP;
}
#endif
#endif /* __linux__ */

int nbd_send_request(QIOChannel *ioc, NBDRequest *request)
{
Loading