/*
- * Copyright (C) 2016-2017 Red Hat, Inc.
+ * Copyright (C) 2016-2018 Red Hat, Inc.
*
* Network Block Device Client Side
nbd_send_opt_abort(ioc);
return -1;
}
- be64_to_cpus(&reply->magic);
- be32_to_cpus(&reply->option);
- be32_to_cpus(&reply->type);
- be32_to_cpus(&reply->length);
+ reply->magic = be64_to_cpu(reply->magic);
+ reply->option = be32_to_cpu(reply->option);
+ reply->type = be32_to_cpu(reply->type);
+ reply->length = be32_to_cpu(reply->length);
trace_nbd_receive_option_reply(reply->option, nbd_opt_lookup(reply->option),
reply->type, nbd_rep_lookup(reply->type),
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;
}
goto cleanup;
}
msg[reply->length] = '\0';
+ trace_nbd_server_error_msg(reply->type,
+ nbd_reply_type_lookup(reply->type), msg);
}
switch (reply->type) {
}
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;
}
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;
}
return -1;
}
len -= sizeof(type);
- be16_to_cpus(&type);
+ type = be16_to_cpu(type);
switch (type) {
case NBD_INFO_EXPORT:
if (len != sizeof(info->size) + sizeof(info->flags)) {
nbd_send_opt_abort(ioc);
return -1;
}
- be64_to_cpus(&info->size);
+ info->size = be64_to_cpu(info->size);
if (nbd_read(ioc, &info->flags, sizeof(info->flags), errp) < 0) {
error_prepend(errp, "failed to read info flags: ");
nbd_send_opt_abort(ioc);
return -1;
}
- be16_to_cpus(&info->flags);
+ info->flags = be16_to_cpu(info->flags);
trace_nbd_receive_negotiate_size_flags(info->size, info->flags);
break;
nbd_send_opt_abort(ioc);
return -1;
}
- be32_to_cpus(&info->min_block);
+ info->min_block = be32_to_cpu(info->min_block);
if (!is_power_of_2(info->min_block)) {
- error_setg(errp, "server minimum block size %" PRId32
- "is not a power of two", info->min_block);
+ error_setg(errp, "server minimum block size %" PRIu32
+ " is not a power of two", info->min_block);
nbd_send_opt_abort(ioc);
return -1;
}
nbd_send_opt_abort(ioc);
return -1;
}
- be32_to_cpus(&info->opt_block);
+ info->opt_block = be32_to_cpu(info->opt_block);
if (!is_power_of_2(info->opt_block) ||
info->opt_block < info->min_block) {
- error_setg(errp, "server preferred block size %" PRId32
- "is not valid", info->opt_block);
+ error_setg(errp, "server preferred block size %" PRIu32
+ " is not valid", info->opt_block);
nbd_send_opt_abort(ioc);
return -1;
}
nbd_send_opt_abort(ioc);
return -1;
}
- be32_to_cpus(&info->max_block);
+ info->max_block = be32_to_cpu(info->max_block);
+ if (info->max_block < info->min_block) {
+ error_setg(errp, "server maximum block size %" PRIu32
+ " is not valid", info->max_block);
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
trace_nbd_opt_go_info_block_size(info->min_block, info->opt_block,
info->max_block);
break;
* Set one meta context. Simple means that reply must contain zero (not
* negotiated) or one (negotiated) contexts. More contexts would be considered
* as a protocol error. It's also implied that meta-data query equals queried
- * context name, so, if server replies with something different then @context,
- * it considered as error too.
+ * context name, so, if server replies with something different than @context,
+ * it is considered an error too.
* return 1 for successful negotiation, context_id is set
* 0 if operation is unsupported,
* -1 with errp set for any other error
{
int ret;
NBDOptionReply reply;
- uint32_t received_id;
- bool received;
+ uint32_t received_id = 0;
+ bool received = false;
uint32_t export_len = strlen(export);
uint32_t context_len = strlen(context);
uint32_t data_len = sizeof(export_len) + export_len +
char *data = g_malloc(data_len);
char *p = data;
+ trace_nbd_opt_meta_request(context, export);
stl_be_p(p, export_len);
memcpy(p += sizeof(export_len), export, export_len);
stl_be_p(p += export_len, 1);
if (reply.type == NBD_REP_META_CONTEXT) {
char *name;
- size_t len;
+
+ if (reply.length != sizeof(received_id) + context_len) {
+ error_setg(errp, "Failed to negotiate meta context '%s', server "
+ "answered with unexpected length %" PRIu32, context,
+ reply.length);
+ nbd_send_opt_abort(ioc);
+ return -1;
+ }
if (nbd_read(ioc, &received_id, sizeof(received_id), errp) < 0) {
return -1;
}
- be32_to_cpus(&received_id);
+ received_id = be32_to_cpu(received_id);
- len = reply.length - sizeof(received_id);
- name = g_malloc(len + 1);
- if (nbd_read(ioc, name, len, errp) < 0) {
+ reply.length -= sizeof(received_id);
+ name = g_malloc(reply.length + 1);
+ if (nbd_read(ioc, name, reply.length, errp) < 0) {
g_free(name);
return -1;
}
- name[len] = '\0';
+ name[reply.length] = '\0';
if (strcmp(context, name)) {
error_setg(errp, "Failed to negotiate meta context '%s', server "
"answered with different context '%s'", context,
name);
g_free(name);
+ nbd_send_opt_abort(ioc);
return -1;
}
g_free(name);
+ trace_nbd_opt_meta_reply(context, received_id);
received = true;
/* receive NBD_REP_ACK */
}
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;
+ }
+ if (reply.length) {
+ error_setg(errp, "Unexpected length to ACK response");
+ nbd_send_opt_abort(ioc);
return -1;
}
if (info->structured_reply && base_allocation) {
result = nbd_negotiate_simple_meta_context(
- ioc, name, "base:allocation",
+ ioc, name, info->x_dirty_bitmap ?: "base:allocation",
&info->meta_base_allocation_id, errp);
if (result < 0) {
goto fail;
error_prepend(errp, "Failed to read export length: ");
goto fail;
}
- be64_to_cpus(&info->size);
+ info->size = be64_to_cpu(info->size);
if (nbd_read(ioc, &info->flags, sizeof(info->flags), errp) < 0) {
error_prepend(errp, "Failed to read export flags: ");
goto fail;
}
- be16_to_cpus(&info->flags);
+ info->flags = be16_to_cpu(info->flags);
} else if (magic == NBD_CLIENT_MAGIC) {
uint32_t oldflags;
error_prepend(errp, "Failed to read export length: ");
goto fail;
}
- be64_to_cpus(&info->size);
+ info->size = be64_to_cpu(info->size);
if (nbd_read(ioc, &oldflags, sizeof(oldflags), errp) < 0) {
error_prepend(errp, "Failed to read export flags: ");
goto fail;
}
- be32_to_cpus(&oldflags);
+ oldflags = be32_to_cpu(oldflags);
if (oldflags & ~0xffff) {
error_setg(errp, "Unexpected export flags %0x" PRIx32, oldflags);
goto fail;
return ret;
}
- be32_to_cpus(&reply->error);
- be64_to_cpus(&reply->handle);
+ reply->error = be32_to_cpu(reply->error);
+ reply->handle = be64_to_cpu(reply->handle);
return 0;
}
return ret;
}
- be16_to_cpus(&chunk->flags);
- be16_to_cpus(&chunk->type);
- be64_to_cpus(&chunk->handle);
- be32_to_cpus(&chunk->length);
+ chunk->flags = be16_to_cpu(chunk->flags);
+ chunk->type = be16_to_cpu(chunk->type);
+ chunk->handle = be64_to_cpu(chunk->handle);
+ chunk->length = be32_to_cpu(chunk->length);
return 0;
}
return ret;
}
- be32_to_cpus(&reply->magic);
+ reply->magic = be32_to_cpu(reply->magic);
switch (reply->magic) {
case NBD_SIMPLE_REPLY_MAGIC: