nbd patches for 2018-01-08

- Eric Blake: 0/2 Optimize sparse reads over NBD
 - Murilo Opsfelder Araujo: block/nbd: fix segmentation fault when .desc is not null-terminated
 -----BEGIN PGP SIGNATURE-----
 Comment: Public key at http://people.redhat.com/eblake/eblake.gpg
 
 iQEcBAABCAAGBQJaU4xvAAoJEKeha0olJ0NqH9IIAJsWiU7WDVXVpnw4RokluQyB
 zbXcP011XOvvsDkmUN09qKectJJ2lbAAzBEhu2axXorP78sIXiVEWwDEtPX/aPpt
 B9irT1muLP3aQIekQRf9soqTs9fPyeiK8/Iy6+E4ad0XwVQ8dMDiGQOhIbiIXQEx
 IitdrS2SGai7H4BXM/E/qYxY4/UWtNHCG9r/2IoWRqTjU2yj2VreMnnjaEJ9GhTk
 PMqn58NPEe7U7xtaqPT1aM8py3V35jC6ucOHUrMpm+NpYY2I3BakVT33x+SFgXZi
 t/Ml53MDK5qh7EeLlosBxbVRf+BKV3+WSdymPRqPuyOUcgOC5iAeIJU5XBoAHvA=
 =eP1e
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2018-01-08' into staging

nbd patches for 2018-01-08

- Eric Blake: 0/2 Optimize sparse reads over NBD
- Murilo Opsfelder Araujo: block/nbd: fix segmentation fault when .desc is not null-terminated

# gpg: Signature made Mon 08 Jan 2018 15:21:19 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-2018-01-08:
  block/nbd: fix segmentation fault when .desc is not null-terminated
  nbd/server: Optimize final chunk of sparse read
  nbd/server: Implement sparse reads atop structured reply

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-01-09 15:22:47 +00:00
commit 3cee4db661
3 changed files with 78 additions and 3 deletions

View File

@ -388,6 +388,7 @@ static QemuOptsList nbd_runtime_opts = {
.type = QEMU_OPT_STRING,
.help = "ID of the TLS credentials to use",
},
{ /* end of list */ }
},
};

View File

@ -1303,6 +1303,7 @@ static int coroutine_fn nbd_co_send_structured_read(NBDClient *client,
uint64_t offset,
void *data,
size_t size,
bool final,
Error **errp)
{
NBDStructuredReadData chunk;
@ -1313,13 +1314,73 @@ static int coroutine_fn nbd_co_send_structured_read(NBDClient *client,
assert(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,
handle, sizeof(chunk) - sizeof(chunk.h) + size);
set_be_chunk(&chunk.h, final ? NBD_REPLY_FLAG_DONE : 0,
NBD_REPLY_TYPE_OFFSET_DATA, handle,
sizeof(chunk) - sizeof(chunk.h) + size);
stq_be_p(&chunk.offset, offset);
return nbd_co_send_iov(client, iov, 2, errp);
}
static int coroutine_fn nbd_co_send_sparse_read(NBDClient *client,
uint64_t handle,
uint64_t offset,
uint8_t *data,
size_t size,
Error **errp)
{
int ret = 0;
NBDExport *exp = client->exp;
size_t progress = 0;
while (progress < size) {
int64_t pnum;
int status = bdrv_block_status_above(blk_bs(exp->blk), NULL,
offset + progress,
size - progress, &pnum, NULL,
NULL);
bool final;
if (status < 0) {
error_setg_errno(errp, -status, "unable to check for holes");
return status;
}
assert(pnum && pnum <= size - progress);
final = progress + pnum == size;
if (status & BDRV_BLOCK_ZERO) {
NBDStructuredReadHole chunk;
struct iovec iov[] = {
{.iov_base = &chunk, .iov_len = sizeof(chunk)},
};
trace_nbd_co_send_structured_read_hole(handle, offset + progress,
pnum);
set_be_chunk(&chunk.h, final ? NBD_REPLY_FLAG_DONE : 0,
NBD_REPLY_TYPE_OFFSET_HOLE,
handle, sizeof(chunk) - sizeof(chunk.h));
stq_be_p(&chunk.offset, offset + progress);
stl_be_p(&chunk.length, pnum);
ret = nbd_co_send_iov(client, iov, 1, errp);
} else {
ret = blk_pread(exp->blk, offset + progress + exp->dev_offset,
data + progress, pnum);
if (ret < 0) {
error_setg_errno(errp, -ret, "reading from file failed");
break;
}
ret = nbd_co_send_structured_read(client, handle, offset + progress,
data + progress, pnum, final,
errp);
}
if (ret < 0) {
break;
}
progress += pnum;
}
return ret;
}
static int coroutine_fn nbd_co_send_structured_error(NBDClient *client,
uint64_t handle,
uint32_t error,
@ -1481,6 +1542,17 @@ static coroutine_fn void nbd_trip(void *opaque)
}
}
if (client->structured_reply && !(request.flags & NBD_CMD_FLAG_DF) &&
request.len) {
ret = nbd_co_send_sparse_read(req->client, request.handle,
request.from, req->data, request.len,
&local_err);
if (ret < 0) {
goto reply;
}
goto done;
}
ret = blk_pread(exp->blk, request.from + exp->dev_offset,
req->data, request.len);
if (ret < 0) {
@ -1561,7 +1633,8 @@ reply:
} else if (reply_data_len) {
ret = nbd_co_send_structured_read(req->client, request.handle,
request.from, req->data,
reply_data_len, &local_err);
reply_data_len, true,
&local_err);
} else {
ret = nbd_co_send_structured_done(req->client, request.handle,
&local_err);

View File

@ -57,6 +57,7 @@ nbd_blk_aio_detach(const char *name, void *ctx) "Export %s: Detaching clients fr
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_hole(uint64_t handle, uint64_t offset, size_t size) "Send structured read hole reply: handle = %" PRIu64 ", offset = %" PRIu64 ", 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_receive_request_decode_type(uint64_t handle, uint16_t type, const char *name) "Decoding type: handle = %" PRIu64 ", type = %" PRIu16 " (%s)"
nbd_co_receive_request_payload_received(uint64_t handle, uint32_t len) "Payload received: handle = %" PRIu64 ", len = %" PRIu32