mirror of https://gitee.com/openkylin/qemu.git
nbd/server: fix sparse read
In case of io error in nbd_co_send_sparse_read we should not "goto reply:", as it was a fatal error and the common behavior is to disconnect in this case. We should not try to send the client an additional error reply, since we already hit a channel-io error on our previous attempt to send one. Fix this by handling block-status error in nbd_co_send_sparse_read, so nbd_co_send_sparse_read fails only on io error. Then just skip common "reply:" code path in nbd_trip. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> Message-Id: <20180308184636.178534-3-vsementsov@virtuozzo.com> [eblake: grammar tweaks] Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
60ace2bacf
commit
37e02aebf8
17
nbd/server.c
17
nbd/server.c
|
@ -1366,6 +1366,10 @@ static int coroutine_fn nbd_co_send_structured_error(NBDClient *client,
|
|||
return nbd_co_send_iov(client, iov, 1 + !!iov[1].iov_len, errp);
|
||||
}
|
||||
|
||||
/* Do a sparse read and send the structured reply to the client.
|
||||
* Returns -errno if sending fails. bdrv_block_status_above() failure is
|
||||
* reported to the client, at which point this function succeeds.
|
||||
*/
|
||||
static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client,
|
||||
uint64_t handle,
|
||||
uint64_t offset,
|
||||
|
@ -1386,8 +1390,13 @@ static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client,
|
|||
bool final;
|
||||
|
||||
if (status < 0) {
|
||||
error_setg_errno(errp, -status, "unable to check for holes");
|
||||
return status;
|
||||
char *msg = g_strdup_printf("unable to check for holes: %s",
|
||||
strerror(-status));
|
||||
|
||||
ret = nbd_co_send_structured_error(client, handle, -status, msg,
|
||||
errp);
|
||||
g_free(msg);
|
||||
return ret;
|
||||
}
|
||||
assert(pnum && pnum <= size - progress);
|
||||
final = progress + pnum == size;
|
||||
|
@ -1568,7 +1577,7 @@ static coroutine_fn void nbd_trip(void *opaque)
|
|||
request.from, req->data, request.len,
|
||||
&local_err);
|
||||
if (ret < 0) {
|
||||
goto reply;
|
||||
goto replied;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
@ -1665,6 +1674,8 @@ reply:
|
|||
req->data, reply_data_len, &local_err);
|
||||
}
|
||||
g_free(msg);
|
||||
|
||||
replied:
|
||||
if (ret < 0) {
|
||||
error_prepend(&local_err, "Failed to send reply: ");
|
||||
goto disconnect;
|
||||
|
|
Loading…
Reference in New Issue