mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 15:53:54 -06:00
nbd/client: prepare nbd_receive_reply for structured reply
In following patch nbd_receive_reply will be used both for simple and structured reply header receiving. NBDReply is altered into union of simple reply header and structured reply chunk header, simple error translation moved to block/nbd-client to be consistent with further structured reply error translation. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <20171027104037.8319-11-eblake@redhat.com>
This commit is contained in:
parent
d795299bf4
commit
d2febedb45
4 changed files with 113 additions and 32 deletions
104
nbd/client.c
104
nbd/client.c
|
@ -908,6 +908,57 @@ int nbd_send_request(QIOChannel *ioc, NBDRequest *request)
|
|||
return nbd_write(ioc, buf, sizeof(buf), NULL);
|
||||
}
|
||||
|
||||
/* nbd_receive_simple_reply
|
||||
* Read simple reply except magic field (which should be already read).
|
||||
* Payload is not read (payload is possible for CMD_READ, but here we even
|
||||
* don't know whether it take place or not).
|
||||
*/
|
||||
static int nbd_receive_simple_reply(QIOChannel *ioc, NBDSimpleReply *reply,
|
||||
Error **errp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
assert(reply->magic == NBD_SIMPLE_REPLY_MAGIC);
|
||||
|
||||
ret = nbd_read(ioc, (uint8_t *)reply + sizeof(reply->magic),
|
||||
sizeof(*reply) - sizeof(reply->magic), errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
be32_to_cpus(&reply->error);
|
||||
be64_to_cpus(&reply->handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* nbd_receive_structured_reply_chunk
|
||||
* Read structured reply chunk except magic field (which should be already
|
||||
* read).
|
||||
* Payload is not read.
|
||||
*/
|
||||
static int nbd_receive_structured_reply_chunk(QIOChannel *ioc,
|
||||
NBDStructuredReplyChunk *chunk,
|
||||
Error **errp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
assert(chunk->magic == NBD_STRUCTURED_REPLY_MAGIC);
|
||||
|
||||
ret = nbd_read(ioc, (uint8_t *)chunk + sizeof(chunk->magic),
|
||||
sizeof(*chunk) - sizeof(chunk->magic), errp);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
be16_to_cpus(&chunk->flags);
|
||||
be16_to_cpus(&chunk->type);
|
||||
be64_to_cpus(&chunk->handle);
|
||||
be32_to_cpus(&chunk->length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* nbd_receive_reply
|
||||
* Returns 1 on success
|
||||
* 0 on eof, when no data was read (errp is not set)
|
||||
|
@ -915,38 +966,47 @@ int nbd_send_request(QIOChannel *ioc, NBDRequest *request)
|
|||
*/
|
||||
int nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp)
|
||||
{
|
||||
uint8_t buf[NBD_REPLY_SIZE];
|
||||
uint32_t magic;
|
||||
int ret;
|
||||
|
||||
ret = nbd_read_eof(ioc, buf, sizeof(buf), errp);
|
||||
ret = nbd_read_eof(ioc, &reply->magic, sizeof(reply->magic), errp);
|
||||
if (ret <= 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reply
|
||||
[ 0 .. 3] magic (NBD_SIMPLE_REPLY_MAGIC)
|
||||
[ 4 .. 7] error (0 == no error)
|
||||
[ 7 .. 15] handle
|
||||
*/
|
||||
be32_to_cpus(&reply->magic);
|
||||
|
||||
magic = ldl_be_p(buf);
|
||||
reply->error = ldl_be_p(buf + 4);
|
||||
reply->handle = ldq_be_p(buf + 8);
|
||||
switch (reply->magic) {
|
||||
case NBD_SIMPLE_REPLY_MAGIC:
|
||||
ret = nbd_receive_simple_reply(ioc, &reply->simple, errp);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
trace_nbd_receive_reply(magic, reply->error, nbd_err_lookup(reply->error),
|
||||
reply->handle);
|
||||
reply->error = nbd_errno_to_system_errno(reply->error);
|
||||
|
||||
if (reply->error == ESHUTDOWN) {
|
||||
/* This works even on mingw which lacks a native ESHUTDOWN */
|
||||
error_setg(errp, "server shutting down");
|
||||
trace_nbd_receive_simple_reply(reply->simple.error,
|
||||
nbd_err_lookup(reply->simple.error),
|
||||
reply->handle);
|
||||
if (reply->simple.error == NBD_ESHUTDOWN) {
|
||||
/* This works even on mingw which lacks a native ESHUTDOWN */
|
||||
error_setg(errp, "server shutting down");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case NBD_STRUCTURED_REPLY_MAGIC:
|
||||
ret = nbd_receive_structured_reply_chunk(ioc, &reply->structured, errp);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
trace_nbd_receive_structured_reply_chunk(reply->structured.flags,
|
||||
reply->structured.type,
|
||||
reply->structured.handle,
|
||||
reply->structured.length);
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "invalid magic (got 0x%" PRIx32 ")", reply->magic);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (magic != NBD_SIMPLE_REPLY_MAGIC) {
|
||||
error_setg(errp, "invalid magic (got 0x%" PRIx32 ")", magic);
|
||||
return -EINVAL;
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue