aboutsummaryrefslogtreecommitdiff
path: root/block/nbd-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/nbd-client.c')
-rw-r--r--block/nbd-client.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/block/nbd-client.c b/block/nbd-client.c
index bfbaf7ebe9..8fe660b609 100644
--- a/block/nbd-client.c
+++ b/block/nbd-client.c
@@ -240,8 +240,8 @@ static int nbd_parse_offset_hole_payload(NBDStructuredReplyChunk *chunk,
}
/* nbd_parse_blockstatus_payload
- * support only one extent in reply and only for
- * base:allocation context
+ * Based on our request, we expect only one extent in reply, for the
+ * base:allocation context.
*/
static int nbd_parse_blockstatus_payload(NBDClientSession *client,
NBDStructuredReplyChunk *chunk,
@@ -250,7 +250,8 @@ static int nbd_parse_blockstatus_payload(NBDClientSession *client,
{
uint32_t context_id;
- if (chunk->length != sizeof(context_id) + sizeof(*extent)) {
+ /* The server succeeded, so it must have sent [at least] one extent */
+ if (chunk->length < sizeof(context_id) + sizeof(*extent)) {
error_setg(errp, "Protocol error: invalid payload for "
"NBD_REPLY_TYPE_BLOCK_STATUS");
return -EINVAL;
@@ -276,10 +277,20 @@ static int nbd_parse_blockstatus_payload(NBDClientSession *client,
return -EINVAL;
}
- /* The server is allowed to send us extra information on the final
- * extent; just clamp it to the length we requested. */
+ /*
+ * We used NBD_CMD_FLAG_REQ_ONE, so the server should not have
+ * sent us any more than one extent, nor should it have included
+ * status beyond our request in that extent. However, it's easy
+ * enough to ignore the server's noncompliance without killing the
+ * connection; just ignore trailing extents, and clamp things to
+ * the length of our request.
+ */
+ if (chunk->length > sizeof(context_id) + sizeof(*extent)) {
+ trace_nbd_parse_blockstatus_compliance("more than one extent");
+ }
if (extent->length > orig_length) {
extent->length = orig_length;
+ trace_nbd_parse_blockstatus_compliance("extent length too large");
}
return 0;