mirror of https://github.com/xemu-project/xemu.git
nbd patches for 2017-11-09
- Vladimir Sementsov-Ogievskiy: nbd/server: fix nbd_negotiate_handle_info - Eric Blake: 0/7 various NBD fixes for 2.11 -----BEGIN PGP SIGNATURE----- Comment: Public key at http://people.redhat.com/eblake/eblake.gpg iQEcBAABCAAGBQJaBIjaAAoJEKeha0olJ0NquwYIAKTloZicVcWpElqvjee5bQkZ ZE6g++zuFc1e1bjWCC0qK1iZ+OFOg0lhbdna2SXLM8GwswBaXWRJDC5uBvwlVuJN 7NK4EVzDlcSYwyQthmLIB5FGB8NZE4U6YK10pH+wIQdhip1aJ11eqXp1UNT3cLVb LyOTkBoCtygTf+nY+WpHhgH+YGZ4bNt1JHIOEk2yhq8xBDsCgKCa1gnWE1TyOuFX 40sr7n2F8+YrPrTeGdk8ZCDDtwhtxawjllJPmbbTmBxClkGQi6rSYUurVtuyzw9c Sz4l0ahzzgyruLDHCef5BfypTzt+AW3PuuGAoaRQhfhBnwzgcMqA71m8gYa0K+0= =K/Rz -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2017-11-09' into staging nbd patches for 2017-11-09 - Vladimir Sementsov-Ogievskiy: nbd/server: fix nbd_negotiate_handle_info - Eric Blake: 0/7 various NBD fixes for 2.11 # gpg: Signature made Thu 09 Nov 2017 16:56:58 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-11-09: nbd/server: Fix structured read of length 0 nbd-client: Stricter enforcing of structured reply spec nbd-client: Short-circuit 0-length operations nbd: Fix struct name for structured reads nbd/client: Nicer trace of structured reply nbd-client: Refuse read-only client with BDRV_O_RDWR nbd-client: Fix error message typos nbd/server: fix nbd_negotiate_handle_info Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
f291910db6
|
@ -216,7 +216,7 @@ static int nbd_parse_offset_hole_payload(NBDStructuredReplyChunk *chunk,
|
||||||
offset = payload_advance64(&payload);
|
offset = payload_advance64(&payload);
|
||||||
hole_size = payload_advance32(&payload);
|
hole_size = payload_advance32(&payload);
|
||||||
|
|
||||||
if (offset < orig_offset || hole_size > qiov->size ||
|
if (!hole_size || offset < orig_offset || hole_size > qiov->size ||
|
||||||
offset > orig_offset + qiov->size - hole_size) {
|
offset > orig_offset + qiov->size - hole_size) {
|
||||||
error_setg(errp, "Protocol error: server sent chunk exceeding requested"
|
error_setg(errp, "Protocol error: server sent chunk exceeding requested"
|
||||||
" region");
|
" region");
|
||||||
|
@ -248,7 +248,7 @@ static int nbd_parse_error_payload(NBDStructuredReplyChunk *chunk,
|
||||||
|
|
||||||
error = nbd_errno_to_system_errno(payload_advance32(&payload));
|
error = nbd_errno_to_system_errno(payload_advance32(&payload));
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
error_setg(errp, "Protocol error: server sent structured error chunk"
|
error_setg(errp, "Protocol error: server sent structured error chunk "
|
||||||
"with error = 0");
|
"with error = 0");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -257,7 +257,7 @@ static int nbd_parse_error_payload(NBDStructuredReplyChunk *chunk,
|
||||||
message_size = payload_advance16(&payload);
|
message_size = payload_advance16(&payload);
|
||||||
|
|
||||||
if (message_size > chunk->length - sizeof(error) - sizeof(message_size)) {
|
if (message_size > chunk->length - sizeof(error) - sizeof(message_size)) {
|
||||||
error_setg(errp, "Protocol error: server sent structured error chunk"
|
error_setg(errp, "Protocol error: server sent structured error chunk "
|
||||||
"with incorrect message size");
|
"with incorrect message size");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -281,7 +281,8 @@ static int nbd_co_receive_offset_data_payload(NBDClientSession *s,
|
||||||
|
|
||||||
assert(nbd_reply_is_structured(&s->reply));
|
assert(nbd_reply_is_structured(&s->reply));
|
||||||
|
|
||||||
if (chunk->length < sizeof(offset)) {
|
/* The NBD spec requires at least one byte of payload */
|
||||||
|
if (chunk->length <= sizeof(offset)) {
|
||||||
error_setg(errp, "Protocol error: invalid payload for "
|
error_setg(errp, "Protocol error: invalid payload for "
|
||||||
"NBD_REPLY_TYPE_OFFSET_DATA");
|
"NBD_REPLY_TYPE_OFFSET_DATA");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -293,6 +294,7 @@ static int nbd_co_receive_offset_data_payload(NBDClientSession *s,
|
||||||
be64_to_cpus(&offset);
|
be64_to_cpus(&offset);
|
||||||
|
|
||||||
data_size = chunk->length - sizeof(offset);
|
data_size = chunk->length - sizeof(offset);
|
||||||
|
assert(data_size);
|
||||||
if (offset < orig_offset || data_size > qiov->size ||
|
if (offset < orig_offset || data_size > qiov->size ||
|
||||||
offset > orig_offset + qiov->size - data_size) {
|
offset > orig_offset + qiov->size - data_size) {
|
||||||
error_setg(errp, "Protocol error: server sent chunk exceeding requested"
|
error_setg(errp, "Protocol error: server sent chunk exceeding requested"
|
||||||
|
@ -408,7 +410,12 @@ static coroutine_fn int nbd_co_do_receive_one_chunk(
|
||||||
if (chunk->type == NBD_REPLY_TYPE_NONE) {
|
if (chunk->type == NBD_REPLY_TYPE_NONE) {
|
||||||
if (!(chunk->flags & NBD_REPLY_FLAG_DONE)) {
|
if (!(chunk->flags & NBD_REPLY_FLAG_DONE)) {
|
||||||
error_setg(errp, "Protocol error: NBD_REPLY_TYPE_NONE chunk without"
|
error_setg(errp, "Protocol error: NBD_REPLY_TYPE_NONE chunk without"
|
||||||
"NBD_REPLY_FLAG_DONE flag set");
|
" NBD_REPLY_FLAG_DONE flag set");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (chunk->length) {
|
||||||
|
error_setg(errp, "Protocol error: NBD_REPLY_TYPE_NONE chunk with"
|
||||||
|
" nonzero length");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -674,6 +681,9 @@ int nbd_client_co_preadv(BlockDriverState *bs, uint64_t offset,
|
||||||
assert(bytes <= NBD_MAX_BUFFER_SIZE);
|
assert(bytes <= NBD_MAX_BUFFER_SIZE);
|
||||||
assert(!flags);
|
assert(!flags);
|
||||||
|
|
||||||
|
if (!bytes) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
ret = nbd_co_send_request(bs, &request, NULL);
|
ret = nbd_co_send_request(bs, &request, NULL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -697,6 +707,7 @@ int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t offset,
|
||||||
.len = bytes,
|
.len = bytes,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
assert(!(client->info.flags & NBD_FLAG_READ_ONLY));
|
||||||
if (flags & BDRV_REQ_FUA) {
|
if (flags & BDRV_REQ_FUA) {
|
||||||
assert(client->info.flags & NBD_FLAG_SEND_FUA);
|
assert(client->info.flags & NBD_FLAG_SEND_FUA);
|
||||||
request.flags |= NBD_CMD_FLAG_FUA;
|
request.flags |= NBD_CMD_FLAG_FUA;
|
||||||
|
@ -704,6 +715,9 @@ int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t offset,
|
||||||
|
|
||||||
assert(bytes <= NBD_MAX_BUFFER_SIZE);
|
assert(bytes <= NBD_MAX_BUFFER_SIZE);
|
||||||
|
|
||||||
|
if (!bytes) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return nbd_co_request(bs, &request, qiov);
|
return nbd_co_request(bs, &request, qiov);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,6 +731,7 @@ int nbd_client_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
|
||||||
.len = bytes,
|
.len = bytes,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
assert(!(client->info.flags & NBD_FLAG_READ_ONLY));
|
||||||
if (!(client->info.flags & NBD_FLAG_SEND_WRITE_ZEROES)) {
|
if (!(client->info.flags & NBD_FLAG_SEND_WRITE_ZEROES)) {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
@ -729,6 +744,9 @@ int nbd_client_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
|
||||||
request.flags |= NBD_CMD_FLAG_NO_HOLE;
|
request.flags |= NBD_CMD_FLAG_NO_HOLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!bytes) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return nbd_co_request(bs, &request, NULL);
|
return nbd_co_request(bs, &request, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,7 +774,8 @@ int nbd_client_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
|
||||||
.len = bytes,
|
.len = bytes,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!(client->info.flags & NBD_FLAG_SEND_TRIM)) {
|
assert(!(client->info.flags & NBD_FLAG_READ_ONLY));
|
||||||
|
if (!(client->info.flags & NBD_FLAG_SEND_TRIM) || !bytes) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -814,6 +833,12 @@ int nbd_client_init(BlockDriverState *bs,
|
||||||
logout("Failed to negotiate with the NBD server\n");
|
logout("Failed to negotiate with the NBD server\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
if (client->info.flags & NBD_FLAG_READ_ONLY &&
|
||||||
|
!bdrv_is_read_only(bs)) {
|
||||||
|
error_setg(errp,
|
||||||
|
"request for write access conflicts with read-only export");
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
if (client->info.flags & NBD_FLAG_SEND_FUA) {
|
if (client->info.flags & NBD_FLAG_SEND_FUA) {
|
||||||
bs->supported_write_flags = BDRV_REQ_FUA;
|
bs->supported_write_flags = BDRV_REQ_FUA;
|
||||||
bs->supported_zero_flags |= BDRV_REQ_FUA;
|
bs->supported_zero_flags |= BDRV_REQ_FUA;
|
||||||
|
|
|
@ -86,15 +86,23 @@ typedef union NBDReply {
|
||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
} NBDReply;
|
} NBDReply;
|
||||||
|
|
||||||
/* Header of NBD_REPLY_TYPE_OFFSET_DATA, complete NBD_REPLY_TYPE_OFFSET_HOLE */
|
/* Header of chunk for NBD_REPLY_TYPE_OFFSET_DATA */
|
||||||
typedef struct NBDStructuredRead {
|
typedef struct NBDStructuredReadData {
|
||||||
NBDStructuredReplyChunk h;
|
NBDStructuredReplyChunk h; /* h.length >= 9 */
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
} QEMU_PACKED NBDStructuredRead;
|
/* At least one byte of data payload follows, calculated from h.length */
|
||||||
|
} QEMU_PACKED NBDStructuredReadData;
|
||||||
|
|
||||||
|
/* Complete chunk for NBD_REPLY_TYPE_OFFSET_HOLE */
|
||||||
|
typedef struct NBDStructuredReadHole {
|
||||||
|
NBDStructuredReplyChunk h; /* h.length == 12 */
|
||||||
|
uint64_t offset;
|
||||||
|
uint32_t length;
|
||||||
|
} QEMU_PACKED NBDStructuredReadHole;
|
||||||
|
|
||||||
/* Header of all NBD_REPLY_TYPE_ERROR* errors */
|
/* Header of all NBD_REPLY_TYPE_ERROR* errors */
|
||||||
typedef struct NBDStructuredError {
|
typedef struct NBDStructuredError {
|
||||||
NBDStructuredReplyChunk h;
|
NBDStructuredReplyChunk h; /* h.length >= 6 */
|
||||||
uint32_t error;
|
uint32_t error;
|
||||||
uint16_t message_length;
|
uint16_t message_length;
|
||||||
} QEMU_PACKED NBDStructuredError;
|
} QEMU_PACKED NBDStructuredError;
|
||||||
|
|
|
@ -979,6 +979,7 @@ static int nbd_receive_structured_reply_chunk(QIOChannel *ioc,
|
||||||
int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp)
|
int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
const char *type;
|
||||||
|
|
||||||
ret = nbd_read_eof(ioc, &reply->magic, sizeof(reply->magic), errp);
|
ret = nbd_read_eof(ioc, &reply->magic, sizeof(reply->magic), errp);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
|
@ -1008,8 +1009,9 @@ int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp)
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
type = nbd_reply_type_lookup(reply->structured.type);
|
||||||
trace_nbd_receive_structured_reply_chunk(reply->structured.flags,
|
trace_nbd_receive_structured_reply_chunk(reply->structured.flags,
|
||||||
reply->structured.type,
|
reply->structured.type, type,
|
||||||
reply->structured.handle,
|
reply->structured.handle,
|
||||||
reply->structured.length);
|
reply->structured.length);
|
||||||
break;
|
break;
|
||||||
|
|
26
nbd/server.c
26
nbd/server.c
|
@ -423,6 +423,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assert(length == 0);
|
||||||
|
|
||||||
exp = nbd_export_find(name);
|
exp = nbd_export_find(name);
|
||||||
if (!exp) {
|
if (!exp) {
|
||||||
|
@ -433,7 +434,7 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint32_t length,
|
||||||
|
|
||||||
/* Don't bother sending NBD_INFO_NAME unless client requested it */
|
/* Don't bother sending NBD_INFO_NAME unless client requested it */
|
||||||
if (sendname) {
|
if (sendname) {
|
||||||
rc = nbd_negotiate_send_info(client, opt, NBD_INFO_NAME, length, name,
|
rc = nbd_negotiate_send_info(client, opt, NBD_INFO_NAME, namelen, name,
|
||||||
errp);
|
errp);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -1272,6 +1273,21 @@ static inline void set_be_chunk(NBDStructuredReplyChunk *chunk, uint16_t flags,
|
||||||
stl_be_p(&chunk->length, length);
|
stl_be_p(&chunk->length, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int coroutine_fn nbd_co_send_structured_done(NBDClient *client,
|
||||||
|
uint64_t handle,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
NBDStructuredReplyChunk chunk;
|
||||||
|
struct iovec iov[] = {
|
||||||
|
{.iov_base = &chunk, .iov_len = sizeof(chunk)},
|
||||||
|
};
|
||||||
|
|
||||||
|
trace_nbd_co_send_structured_done(handle);
|
||||||
|
set_be_chunk(&chunk, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_NONE, handle, 0);
|
||||||
|
|
||||||
|
return nbd_co_send_iov(client, iov, 1, errp);
|
||||||
|
}
|
||||||
|
|
||||||
static int coroutine_fn nbd_co_send_structured_read(NBDClient *client,
|
static int coroutine_fn nbd_co_send_structured_read(NBDClient *client,
|
||||||
uint64_t handle,
|
uint64_t handle,
|
||||||
uint64_t offset,
|
uint64_t offset,
|
||||||
|
@ -1279,12 +1295,13 @@ static int coroutine_fn nbd_co_send_structured_read(NBDClient *client,
|
||||||
size_t size,
|
size_t size,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
NBDStructuredRead chunk;
|
NBDStructuredReadData chunk;
|
||||||
struct iovec iov[] = {
|
struct iovec iov[] = {
|
||||||
{.iov_base = &chunk, .iov_len = sizeof(chunk)},
|
{.iov_base = &chunk, .iov_len = sizeof(chunk)},
|
||||||
{.iov_base = data, .iov_len = size}
|
{.iov_base = data, .iov_len = size}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
assert(size);
|
||||||
trace_nbd_co_send_structured_read(handle, offset, data, size);
|
trace_nbd_co_send_structured_read(handle, offset, data, size);
|
||||||
set_be_chunk(&chunk.h, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_OFFSET_DATA,
|
set_be_chunk(&chunk.h, NBD_REPLY_FLAG_DONE, NBD_REPLY_TYPE_OFFSET_DATA,
|
||||||
handle, sizeof(chunk) - sizeof(chunk.h) + size);
|
handle, sizeof(chunk) - sizeof(chunk.h) + size);
|
||||||
|
@ -1543,10 +1560,13 @@ reply:
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
ret = nbd_co_send_structured_error(req->client, request.handle,
|
ret = nbd_co_send_structured_error(req->client, request.handle,
|
||||||
-ret, msg, &local_err);
|
-ret, msg, &local_err);
|
||||||
} else {
|
} else if (reply_data_len) {
|
||||||
ret = nbd_co_send_structured_read(req->client, request.handle,
|
ret = nbd_co_send_structured_read(req->client, request.handle,
|
||||||
request.from, req->data,
|
request.from, req->data,
|
||||||
reply_data_len, &local_err);
|
reply_data_len, &local_err);
|
||||||
|
} else {
|
||||||
|
ret = nbd_co_send_structured_done(req->client, request.handle,
|
||||||
|
&local_err);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = nbd_co_send_simple_reply(req->client, request.handle,
|
ret = nbd_co_send_simple_reply(req->client, request.handle,
|
||||||
|
|
|
@ -27,7 +27,7 @@ nbd_client_clear_queue(void) "Clearing NBD queue"
|
||||||
nbd_client_clear_socket(void) "Clearing NBD socket"
|
nbd_client_clear_socket(void) "Clearing NBD socket"
|
||||||
nbd_send_request(uint64_t from, uint32_t len, uint64_t handle, uint16_t flags, uint16_t type, const char *name) "Sending request to server: { .from = %" PRIu64", .len = %" PRIu32 ", .handle = %" PRIu64 ", .flags = 0x%" PRIx16 ", .type = %" PRIu16 " (%s) }"
|
nbd_send_request(uint64_t from, uint32_t len, uint64_t handle, uint16_t flags, uint16_t type, const char *name) "Sending request to server: { .from = %" PRIu64", .len = %" PRIu32 ", .handle = %" PRIu64 ", .flags = 0x%" PRIx16 ", .type = %" PRIu16 " (%s) }"
|
||||||
nbd_receive_simple_reply(int32_t error, const char *errname, uint64_t handle) "Got simple reply: { .error = %" PRId32 " (%s), handle = %" PRIu64" }"
|
nbd_receive_simple_reply(int32_t error, const char *errname, uint64_t handle) "Got simple reply: { .error = %" PRId32 " (%s), handle = %" PRIu64" }"
|
||||||
nbd_receive_structured_reply_chunk(uint16_t flags, uint16_t type, uint64_t handle, uint32_t length) "Got structured reply chunk: { flags = 0x%" PRIx16 ", type = %d, handle = %" PRIu64 ", length = %" PRIu32 " }"
|
nbd_receive_structured_reply_chunk(uint16_t flags, uint16_t type, const char *name, uint64_t handle, uint32_t length) "Got structured reply chunk: { flags = 0x%" PRIx16 ", type = %d (%s), handle = %" PRIu64 ", length = %" PRIu32 " }"
|
||||||
|
|
||||||
# nbd/common.c
|
# nbd/common.c
|
||||||
nbd_unknown_error(int err) "Squashing unexpected error %d to EINVAL"
|
nbd_unknown_error(int err) "Squashing unexpected error %d to EINVAL"
|
||||||
|
@ -55,6 +55,7 @@ nbd_receive_request(uint32_t magic, uint16_t flags, uint16_t type, uint64_t from
|
||||||
nbd_blk_aio_attached(const char *name, void *ctx) "Export %s: Attaching clients to AIO context %p\n"
|
nbd_blk_aio_attached(const char *name, void *ctx) "Export %s: Attaching clients to AIO context %p\n"
|
||||||
nbd_blk_aio_detach(const char *name, void *ctx) "Export %s: Detaching clients from AIO context %p\n"
|
nbd_blk_aio_detach(const char *name, void *ctx) "Export %s: Detaching clients from AIO context %p\n"
|
||||||
nbd_co_send_simple_reply(uint64_t handle, uint32_t error, const char *errname, int len) "Send simple reply: handle = %" PRIu64 ", error = %" PRIu32 " (%s), len = %d"
|
nbd_co_send_simple_reply(uint64_t handle, uint32_t error, const char *errname, int len) "Send simple reply: handle = %" PRIu64 ", error = %" PRIu32 " (%s), len = %d"
|
||||||
|
nbd_co_send_structured_done(uint64_t handle) "Send structured reply done: handle = %" PRIu64
|
||||||
nbd_co_send_structured_read(uint64_t handle, uint64_t offset, void *data, size_t size) "Send structured read data reply: handle = %" PRIu64 ", offset = %" PRIu64 ", data = %p, len = %zu"
|
nbd_co_send_structured_read(uint64_t handle, uint64_t offset, void *data, size_t size) "Send structured read data reply: handle = %" PRIu64 ", offset = %" PRIu64 ", data = %p, len = %zu"
|
||||||
nbd_co_send_structured_error(uint64_t handle, int err, const char *errname, const char *msg) "Send structured error reply: handle = %" PRIu64 ", error = %d (%s), msg = '%s'"
|
nbd_co_send_structured_error(uint64_t handle, int err, const char *errname, const char *msg) "Send structured error reply: handle = %" PRIu64 ", error = %d (%s), msg = '%s'"
|
||||||
nbd_co_receive_request_decode_type(uint64_t handle, uint16_t type, const char *name) "Decoding type: handle = %" PRIu64 ", type = %" PRIu16 " (%s)"
|
nbd_co_receive_request_decode_type(uint64_t handle, uint16_t type, const char *name) "Decoding type: handle = %" PRIu64 ", type = %" PRIu16 " (%s)"
|
||||||
|
|
|
@ -117,15 +117,15 @@ _export_nbd_snapshot sn1
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "== verifying the exported snapshot with patterns, method 1 =="
|
echo "== verifying the exported snapshot with patterns, method 1 =="
|
||||||
$QEMU_IO_NBD -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
|
$QEMU_IO_NBD -r -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
|
||||||
$QEMU_IO_NBD -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
|
$QEMU_IO_NBD -r -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
|
||||||
|
|
||||||
_export_nbd_snapshot1 sn1
|
_export_nbd_snapshot1 sn1
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "== verifying the exported snapshot with patterns, method 2 =="
|
echo "== verifying the exported snapshot with patterns, method 2 =="
|
||||||
$QEMU_IO_NBD -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
|
$QEMU_IO_NBD -r -c 'read -P 0xa 0x1000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
|
||||||
$QEMU_IO_NBD -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
|
$QEMU_IO_NBD -r -c 'read -P 0xb 0x2000 0x1000' "$nbd_snapshot_img" | _filter_qemu_io
|
||||||
|
|
||||||
$QEMU_IMG convert "$TEST_IMG" -l sn1 -O qcow2 "$converted_image"
|
$QEMU_IMG convert "$TEST_IMG" -l sn1 -O qcow2 "$converted_image"
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ _send_qemu_cmd $QEMU_HANDLE \
|
||||||
'arguments': { 'device': 'drv' }}" \
|
'arguments': { 'device': 'drv' }}" \
|
||||||
'return'
|
'return'
|
||||||
|
|
||||||
$QEMU_IO_PROG -f raw -c 'read -P 42 0 64k' \
|
$QEMU_IO_PROG -f raw -r -c 'read -P 42 0 64k' \
|
||||||
"nbd+unix:///drv?socket=$TEST_DIR/nbd" 2>&1 \
|
"nbd+unix:///drv?socket=$TEST_DIR/nbd" 2>&1 \
|
||||||
| _filter_qemu_io | _filter_nbd
|
| _filter_qemu_io | _filter_nbd
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ _send_qemu_cmd $QEMU_HANDLE \
|
||||||
'arguments': { 'device': 'drv' }}" \
|
'arguments': { 'device': 'drv' }}" \
|
||||||
'return'
|
'return'
|
||||||
|
|
||||||
$QEMU_IO_PROG -f raw -c close \
|
$QEMU_IO_PROG -f raw -r -c close \
|
||||||
"nbd+unix:///drv?socket=$TEST_DIR/nbd" 2>&1 \
|
"nbd+unix:///drv?socket=$TEST_DIR/nbd" 2>&1 \
|
||||||
| _filter_qemu_io | _filter_nbd
|
| _filter_qemu_io | _filter_nbd
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ class NBDBlockdevAddBase(iotests.QMPTestCase):
|
||||||
'driver': 'raw',
|
'driver': 'raw',
|
||||||
'file': {
|
'file': {
|
||||||
'driver': 'nbd',
|
'driver': 'nbd',
|
||||||
|
'read-only': True,
|
||||||
'server': address
|
'server': address
|
||||||
} }
|
} }
|
||||||
if export is not None:
|
if export is not None:
|
||||||
|
|
Loading…
Reference in New Issue